package com.example.demo04plc.plc.modbus.tcp;

import HslCommunication.Core.Types.OperateResult;
import HslCommunication.Core.Types.OperateResultExOne;
import HslCommunication.ModBus.ModbusTcpNet;
import cn.hutool.core.util.ReflectUtil;
import com.example.demo04plc.plc.common.*;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executors;

@Slf4j
public class ModbusTcpConnection extends AbstractPlcConnection {

    private ModbusTcpNet modbusTcpNet;
    private PlcConnectionConfig plcConnectionConfig;
    private static final Map<String, String> DATA_TYPE = new HashMap<>(){{
       put("bool", "Bool");
       put("short", "Int16");
       put("int", "Int32");
       put("long", "Int64");
       put("float", "Float");
       put("double", "Double");
    }};

    public ModbusTcpConnection(String deviceId) {
        super(deviceId);
    }


    @Override
    public PlcConnectionConfig getConnectionConfig() {
        return plcConnectionConfig;
    }

    @Override
    public OperateResult connect(PlcConnectionConfig connectionConfig) {

        this.plcConnectionConfig = connectionConfig;
        if (!"modbus-tcp".equals(connectionConfig.getTransport())) {
            return new OperateResult(-1, String.format("不支持的传输%s", connectionConfig.getTransport()));
        }
        modbusTcpNet = new ModbusTcpNet(connectionConfig.getIpAddress(),
                connectionConfig.getPort(),
                Byte.parseByte(Optional.ofNullable(connectionConfig.getOptions().get("station"))
                        .orElseThrow(() -> new RuntimeException("从站地址不能为空"))));
        return modbusTcpNet.ConnectServer();
    }

    @Override
    public boolean isConnected() {
        return modbusTcpNet != null;
    }

    @Override
    public OperateResult close() {
        if (!isConnected()) {
            return new OperateResult(-1,"未建立连接");
        }
        return modbusTcpNet.ConnectClose();
    }

    @Override
    public PlcReadResponse read(PlcReadRequest plcReadRequest) {
        if (!isConnected()) {
            throw new RuntimeException("未建立连接");
        }
        PlcReadResponse plcReadResponse = new ModbusTcpReadResponse();
        Map<String, String> items = plcReadRequest.getItems();

        items.forEach((key, fieldQuery) -> {
            String[] split = fieldQuery.split(":");
            OperateResultExOne<?> resultExOne = ReflectUtil.invoke(modbusTcpNet,
                    "Read" + Optional.ofNullable(DATA_TYPE.get(split[0])).orElseThrow(() -> new RuntimeException(String.format("不支持的数据类型[%s]", split[0]))),
                    split[1]);
            plcReadResponse.addResult(key, resultExOne);
        });
        return plcReadResponse;
    }

}
